package com.platform.net;

import android.util.Log;

import com.platform.contact.ServerConfig;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentLinkedQueue;

public class NetPlatform {

	public static final int DataLength=2048;
	private ConcurrentLinkedQueue<DatagramPacket> recvPacketQueue = new ConcurrentLinkedQueue<>();
	private ConcurrentLinkedQueue<DatagramPacket> sendPacketQueue = new ConcurrentLinkedQueue<>();
	private DatagramSocket socket;
	private OnRecvCallback onRecvCallback;
	private Object sendObj = new Object();
	private Object recvObj = new Object();
	
	public interface OnRecvCallback{
		void onCallback(String json);
	} 
	
	public NetPlatform(OnRecvCallback onRecvCallback) {
		this.onRecvCallback = onRecvCallback;
		new ListenerThread().start();
		new HandlerThread().start();
		new SendThread().start();
		new ClearThread().start();
	}
	
	private class ClearThread extends Thread{
		
		@Override
		public void run() {
			while(true){
				try {
					Log.d("androidLog","PacketQueue size is "+ (recvPacketQueue.size()+sendPacketQueue.size()));
					System.gc();
					Thread.sleep(60000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private class ListenerThread extends Thread{
		
		@Override
		public void run() {
			try {
				socket = new DatagramSocket();
				while(true){
					try {
						byte buf[] = new byte[DataLength];
						DatagramPacket packet = new DatagramPacket(buf, buf.length);
						socket.receive(packet);
						recvPacketQueue.add(packet);
						synchronized (recvObj){
							recvObj.notifyAll();
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} catch (SocketException e) {
				e.printStackTrace();
			}
		}
	}
	
	private class HandlerThread extends Thread{
		@Override
		public void run() {
			
			while(true){

				try {
					if(!recvPacketQueue.isEmpty()){
						DatagramPacket packet = recvPacketQueue.poll();
						if(onRecvCallback!=null&&packet!=null){
							String json = new String(packet.getData(),0,packet.getLength());
							onRecvCallback.onCallback(json);
							Log.d("androidLog","recv::"+json);
						}
					}else{
						synchronized (recvObj){
							recvObj.wait();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		}
	}

	private class SendThread extends Thread{
		@Override
		public void run() {
			while (true){
				try{
					if(!sendPacketQueue.isEmpty()){
						try {
							DatagramPacket packet = sendPacketQueue.poll();
							socket.send(packet);
						} catch (IOException e) {
							e.printStackTrace();
						}
					}else{
						synchronized (sendObj){
							sendObj.wait();
						}
					}
				}catch (Exception e){
					e.printStackTrace();
				}

			}
		}
	}

	
	public void send(String json){
		try {
			Log.d("androidLog","send::"+json);
			InetAddress inetAddress = InetAddress.getByName(ServerConfig.ServerIp);
			DatagramPacket packet = new DatagramPacket(json.getBytes(),json.length(),inetAddress,ServerConfig.ServerPort);
			sendPacketQueue.add(packet);
			synchronized (sendObj){
				sendObj.notifyAll();
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}
}
